From d52d31e3cc0c813301f83d6b02131ebe5c34b88a Mon Sep 17 00:00:00 2001 From: "mjw@wray-m-3.hpl.hp.com" Date: Fri, 25 Jun 2004 13:19:35 +0000 Subject: [PATCH] bitkeeper revision 1.1010.1.7 (40dc2667VP5fW6QI61kdgU_iNS2Pnw) Tidy up console destruction on domain exit. --- tools/xenmgr/lib/EventServer.py | 24 +++++++++++++++------ tools/xenmgr/lib/XendConsole.py | 17 +++++++++------ tools/xenmgr/lib/XendDomain.py | 20 ++++++++++------- tools/xenmgr/lib/server/SrvConsoleDir.py | 3 ++- tools/xenmgr/lib/server/SrvConsoleServer.py | 14 +++++++++--- tools/xenmgr/lib/server/SrvDomainDir.py | 5 +++-- tools/xenmgr/lib/server/channel.py | 20 ++++++++++------- tools/xenmgr/lib/server/console.py | 20 ++++++++++++----- tools/xenmgr/lib/server/controller.py | 10 ++++++--- 9 files changed, 90 insertions(+), 43 deletions(-) diff --git a/tools/xenmgr/lib/EventServer.py b/tools/xenmgr/lib/EventServer.py index 6fae2b9ccf..20c567ada7 100644 --- a/tools/xenmgr/lib/EventServer.py +++ b/tools/xenmgr/lib/EventServer.py @@ -4,6 +4,8 @@ """ import string +from twisted.internet import reactor + # subscribe a.b.c h: map a.b.c -> h # subscribe a.b.* h: map a.b.* -> h # subscribe a.b.? h: map a.b.? -> h @@ -73,7 +75,7 @@ class EventServer: """ if event == None: self.handlers.clear() - else: + elif event in self.handlers: del self.handlers[event] def unsubscribe(self, event, handler): @@ -88,21 +90,29 @@ class EventServer: if handler in hl: hl.remove(handler) - def inject(self, event, val): - """Inject an event. Handlers for it are called if runing, otherwise + def inject(self, event, val, async=1): + """Inject an event. Handlers for it are called if running, otherwise it is queued. event event type val event value """ if self.run: - #print ">event", event, val - self.call_event_handlers(event, event, val) - self.call_query_handlers(event, val) - self.call_star_handlers(event, val) + if async: + reactor.callLater(0, self.call_handlers, event, val) + else: + self.notify_handlers(event, val) else: self.queue.append( (event, val) ) + def call_handlers(self, event, val): + """Internal method to call event handlers. + """ + #print ">event", event, val + self.call_event_handlers(event, event, val) + self.call_query_handlers(event, val) + self.call_star_handlers(event, val) + def call_event_handlers(self, key, event, val): """Call the handlers for an event. It is safe for handlers to subscribe or unsubscribe. diff --git a/tools/xenmgr/lib/XendConsole.py b/tools/xenmgr/lib/XendConsole.py index 19ad7eeae3..dcf992d376 100644 --- a/tools/xenmgr/lib/XendConsole.py +++ b/tools/xenmgr/lib/XendConsole.py @@ -21,10 +21,10 @@ class XendConsoleInfo: def __init__(self, console, dom1, port1, dom2, port2, conn=None): self.console = console - self.dom1 = dom1 - self.port1 = port1 - self.dom2 = dom2 - self.port2 = port2 + self.dom1 = int(dom1) + self.port1 = int(port1) + self.dom2 = int(dom2) + self.port2 = int(port2) self.conn = conn #self.id = "%d.%d-%d.%d" % (self.dom1, self.port1, self.dom2, self.port2) self.id = str(port1) @@ -81,6 +81,7 @@ class XendConsole: print 'XendConsole> rebooted: removing all console info' self.rm_all() eserver.subscribe('xend.domain.died', self.onDomainDied) + eserver.subscribe('xend.domain.destroy', self.onDomainDied) def rm_all(self): """Remove all console info. Used after reboot. @@ -104,11 +105,15 @@ class XendConsole: self._delete_console(c.id) def onDomainDied(self, event, val): - print 'onDomainDied', "dom=", dom, dom = int(val) + #print 'XendConsole>onDomainDied', 'event', event, "dom=", dom for c in self.consoles(): - print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2 + #print 'onDomainDied', "dom=", dom, "dom1=", c.dom1, "dom2=", c.dom2 if (c.dom1 == dom) or (c.dom2 == dom): + 'XendConsole>onDomainDied', 'delete console dom=', dom + ctrl = xcd.get_domain_console(dom) + if ctrl: + ctrl.close() self._delete_console(c.id) def sync(self): diff --git a/tools/xenmgr/lib/XendDomain.py b/tools/xenmgr/lib/XendDomain.py index 5c31079b2e..2eaa9b6241 100644 --- a/tools/xenmgr/lib/XendDomain.py +++ b/tools/xenmgr/lib/XendDomain.py @@ -79,11 +79,10 @@ class XendDomain: self._delete_domain(domid) deferred = defer.DeferredList(dlist, fireOnOneErrback=1) def cbok(val): - print "doms:" - for d in self.domain.values(): print 'dom', d - print "refresh..." + #print "doms:" + #for d in self.domain.values(): print 'dom', d self.refresh() - print "doms:" + print "XendDomain>initial_refresh> doms:" for d in self.domain.values(): print 'dom', d deferred.addCallback(cbok) @@ -148,11 +147,14 @@ class XendDomain: self.db.delete(id) def reap(self): - print 'reap>' + """Go through the domains looking for ones that have crashed or stopped. + Tidy them up. + """ + print 'XendDomain>reap>' domlist = xc.domain_getinfo() casualties = [] for d in domlist: - print 'dom', d + #print 'dom', d dead = 0 dead = dead or (d['crashed'] or d['shutdown']) dead = dead or (d['dying'] and @@ -161,12 +163,12 @@ class XendDomain: casualties.append(d) for d in casualties: id = str(d['dom']) - print 'died> id=', id, d + print 'XendDomain>reap> died id=', id, d dominfo = self.domain.get(id) if not dominfo: continue dominfo.died() self.domain_destroy(id, refresh=0) - print 'reap<' + print 'XendDomain>reap<' def refresh(self): """Refresh domain list from Xen. @@ -203,6 +205,8 @@ class XendDomain: try: self._delete_domain(id) except: + print 'refresh_domain: error' + raise pass else: d = self.domain.get(id) diff --git a/tools/xenmgr/lib/server/SrvConsoleDir.py b/tools/xenmgr/lib/server/SrvConsoleDir.py index 89b092c18d..e5c0308f80 100644 --- a/tools/xenmgr/lib/server/SrvConsoleDir.py +++ b/tools/xenmgr/lib/server/SrvConsoleDir.py @@ -18,7 +18,8 @@ class SrvConsoleDir(SrvDir): try: info = self.xconsole.console_get(x) val = SrvConsole(info) - except KeyError: + except KeyError, ex: + print 'SrvConsoleDir>', ex pass return val diff --git a/tools/xenmgr/lib/server/SrvConsoleServer.py b/tools/xenmgr/lib/server/SrvConsoleServer.py index f3316fef1c..d6bb976b3c 100644 --- a/tools/xenmgr/lib/server/SrvConsoleServer.py +++ b/tools/xenmgr/lib/server/SrvConsoleServer.py @@ -378,7 +378,10 @@ class EventProtocol(protocol.Protocol): return ['ok'] def op_info(self, name, req): - val = self.daemon.consoles() + val = ['info'] + val += self.daemon.consoles() + val += self.daemon.blkifs() + val += self.daemon.netifs() return val def op_sys_subscribe(self, name, v): @@ -603,6 +606,9 @@ class Daemon: d = self.blkifCF.createInstance(dom, recreate=recreate) return d + def blkifs(self): + return [ x.sxpr() for x in self.blkifCF.getInstances() ] + def blkif_get(self, dom): return self.blkifCF.getInstanceByDom(dom) @@ -637,6 +643,9 @@ class Daemon: """ return self.netifCF.createInstance(dom, recreate=recreate) + def netifs(self): + return [ x.sxpr() for x in self.netifCF.getInstances() ] + def netif_get(self, dom): return self.netifCF.getInstanceByDom(dom) @@ -677,8 +686,7 @@ class Daemon: console = self.get_console(id) if not console: raise ValueError('Invalid console id') - if console.conn: - console.conn.loseConnection() + console.disconnect() def domain_shutdown(self, dom, reason): """Shutdown a domain. diff --git a/tools/xenmgr/lib/server/SrvDomainDir.py b/tools/xenmgr/lib/server/SrvDomainDir.py index 7bb2996d9b..67a6a9bc7f 100644 --- a/tools/xenmgr/lib/server/SrvDomainDir.py +++ b/tools/xenmgr/lib/server/SrvDomainDir.py @@ -24,7 +24,8 @@ class SrvDomainDir(SrvDir): try: dom = self.xd.domain_get(x) val = SrvDomain(dom) - except KeyError: + except KeyError, ex: + print 'SrvDomainDir>', ex pass return val @@ -46,7 +47,7 @@ class SrvDomainDir(SrvDir): config = pin.get_val() ok = 1 except Exception, ex: - print ex + print 'op_create>', ex if not ok: req.setResponseCode(http.BAD_REQUEST, "Invalid configuration") return "Invalid configuration" diff --git a/tools/xenmgr/lib/server/channel.py b/tools/xenmgr/lib/server/channel.py index 3f2a7a6382..cf890918e5 100755 --- a/tools/xenmgr/lib/server/channel.py +++ b/tools/xenmgr/lib/server/channel.py @@ -49,6 +49,7 @@ class ChannelFactory: """Get the channel for the given domain. Construct if necessary. """ + dom = int(dom) for chan in self.channels.values(): if not isinstance(chan, Channel): continue if chan.dom == dom: @@ -199,7 +200,7 @@ class Channel(BaseChannel): """ BaseChannel.__init__(self, factory) # Domain. - self.dom = dom + self.dom = int(dom) # Domain port (object). self.port = self.factory.createPort(dom) # Channel port (int). @@ -210,6 +211,7 @@ class Channel(BaseChannel): self.devs_by_type = {} # Output queue. self.queue = [] + self.closed = 0 def getLocalPort(self): """Get the local port. @@ -225,11 +227,12 @@ class Channel(BaseChannel): """Close the channel. Calls lostChannel() on all its devices and channelClosed() on the factory. """ + self.closed = 1 for d in self.devs: d.lostChannel() self.factory.channelClosed(self) - del self.devs - del self.devs_by_type + self.devs = [] + self.devs_by_type = {} def registerDevice(self, types, dev): """Register a device controller. @@ -237,20 +240,21 @@ class Channel(BaseChannel): @param types message types the controller handles @param dev device controller """ + if self.closed: return self.devs.append(dev) for ty in types: self.devs_by_type[ty] = dev - def unregisterDevice(self, dev): + def deregisterDevice(self, dev): """Remove the registration for a device controller. @param dev device controller """ - self.devs.remove(dev) - types = [ ty for (ty, d) in self.devs_by_type.items() - if d == dev ] + if dev in self.devs: + self.devs.remove(dev) + types = [ ty for (ty, d) in self.devs_by_type.items() if d == dev ] for ty in types: - del devs_by_type[ty] + del self.devs_by_type[ty] def getDevice(self, type): """Get the device controller handling a message type. diff --git a/tools/xenmgr/lib/server/console.py b/tools/xenmgr/lib/server/console.py index 6db905dc0b..f26a4dd3c6 100755 --- a/tools/xenmgr/lib/server/console.py +++ b/tools/xenmgr/lib/server/console.py @@ -103,7 +103,7 @@ class ConsoleController(controller.Controller): """ def __init__(self, factory, dom, console_port): - #print 'ConsoleController> dom=', dom + #print 'ConsoleController> dom=', dom, type(dom) controller.Controller.__init__(self, factory, dom) self.majorTypes = [ CMSG_CONSOLE ] self.status = "new" @@ -120,6 +120,7 @@ class ConsoleController(controller.Controller): def sxpr(self): val =['console', + ['status', self.status ], ['id', self.idx ], ['domain', self.dom ], ['local_port', self.channel.getLocalPort() ], @@ -139,10 +140,17 @@ class ConsoleController(controller.Controller): return self.status == 'connected' def close(self): - self.status = "closed" - self.listener.stopListening() - self.deregisterChannel() - self.lostChannel() + try: + #print 'ConsoleController> close dom=', self.dom + self.status = "closed" + if self.conn: + self.conn.loseConnection() + self.listener.stopListening() + self.deregisterChannel() + self.lostChannel() + except Exception, ex: + print 'ConsoleController>close>', ex + raise def listen(self): """Listen for TCP connections to the console port.. @@ -166,6 +174,8 @@ class ConsoleController(controller.Controller): return 0 def disconnect(self): + if self.conn: + self.conn.loseConnection() self.addr = None self.conn = None self.listen() diff --git a/tools/xenmgr/lib/server/controller.py b/tools/xenmgr/lib/server/controller.py index 08afdfd634..900c2d55b0 100755 --- a/tools/xenmgr/lib/server/controller.py +++ b/tools/xenmgr/lib/server/controller.py @@ -36,14 +36,14 @@ class CtrlMsgRcvr: pass def registerChannel(self): - print 'CtrlMsgRcvr>registerChannel>', self + #print 'CtrlMsgRcvr>registerChannel>', self self.channel = self.channelFactory.domChannel(self.dom) self.idx = self.channel.getIndex() if self.majorTypes: self.channel.registerDevice(self.majorTypes, self) def deregisterChannel(self): - print 'CtrlMsgRcvr>deregisterChannel>', self + #print 'CtrlMsgRcvr>deregisterChannel>', self if self.channel: self.channel.deregisterDevice(self) del self.channel @@ -92,13 +92,16 @@ class ControllerFactory(CtrlMsgRcvr): return None def delInstance(self, instance): + #print 'ControllerFactory>delInstance>', instance.idx if instance.idx in self.instances: + #print 'ControllerFactory>delInstance> remove', instance.idx del self.instances[instance.idx] def createInstance(self, dom, recreate=0): raise NotImplementedError() def instanceClosed(self, instance): + #print 'ControllerFactory>instanceClosed>', instance.idx, instance self.delInstance(instance) def addDeferred(self): @@ -126,7 +129,7 @@ class Controller(CtrlMsgRcvr): def __init__(self, factory, dom): CtrlMsgRcvr.__init__(self) self.factory = factory - self.dom = dom + self.dom = int(dom) self.channel = None self.idx = None @@ -135,6 +138,7 @@ class Controller(CtrlMsgRcvr): self.lostChannel() def lostChannel(self): + #print 'Controller>lostChannel>', self, self.factory self.factory.instanceClosed(self) class Dev: -- 2.30.2